/*
 * 文件名：middle.cpp
 * 功能描述：棋盘状态管理和棋子移动逻辑
 */
#include <Arduino.h> // 引入 Arduino 库
#include "middle.h"  // 引入中间状态库
#include "hall_id.h"

// 在此处定义这些全局变量
char rotatedArr[10][10]; // 存储旋转后的二维数组
char finalArr[10][10];   // 存储旋转并水平翻转后的二维数组
char arr2D[10][10];      // 存储原始二维数组
String idBoard[10][10];  // 棋子id
String id_board = "";
String pieces[] = {
    "RW", "NW", "BW", "QW", "KW", "PW", // 白棋
    "RB", "NB", "BB", "QB", "KB", "PB"  // 黑棋
};

// 在全局区域添加字符串分割函数
std::vector<String> splitString(const String &str, char delimiter)
{
    std::vector<String> tokens;
    int start = 0;
    int end = str.indexOf(delimiter);
    while (end != -1)
    {
        tokens.push_back(str.substring(start, end));
        start = end + 1;
        end = str.indexOf(delimiter, start);
    }
    tokens.push_back(str.substring(start));
    return tokens;
}

// 新增函数：将FEN转换为棋盘位置数组
std::vector<FenPosition> parseFEN(const String &fen)
{
    std::vector<FenPosition> positions;
    int row = 7; // FEN从第8行开始（棋盘底部）
    int col = 1; // 从a列开始

    for (char c : fen)
    {
        if (c == '/')
        {
            row--;
            col = 1;
        }
        else if (isdigit(c))
        {
            col += c - '0';
        }
        else
        {
            FenPosition pos;
            pos.piece = String(c);
            pos.gridPos = String(char('a' + (col - 1))) + String(8 - row);
            positions.push_back(pos);
            col++;
        }
        if (row < 0)
            break; // 防止越界
    }
    return positions;
}

// 用于记录最后两步棋的数组
String lastMovesstart[2]; // 存储每步棋的起始位置，例如 "E2"
String lastMovesend[2];   // 存储每步棋的结束位置，例如 "E4"
int lastMovesMagn[2];     // 存储每步棋所使用的电磁铁编号

std::map<String, PieceRecord> pieceRecords;

String QW = "QW";
String QB = "QB";
// 网格（棋盘）位置定义，包含每个单元格的标识符
const String grid[10][10] = {
    {"00", "10", "20", "30", "40", "50", "60", "70", "80", "90"}, // 第一行（左下角）
    {"01", "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1", "91"},
    {"02", "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2", "92"},
    {"03", "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3", "93"},
    {"04", "a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4", "94"},
    {"05", "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5", "95"},
    {"06", "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6", "96"},
    {"07", "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7", "97"},
    {"08", "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8", "98"},
    {"09", "19", "29", "39", "49", "59", "69", "79", "89", "99"}, // 最后一行（右上角）
};

// 直接定义棋盘位置上的棋子
String id_w[10][10] = {
    {"+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ "},
    {"+ ", "RW1", "NW1", "BW1", "QW1", "KW2", "BW2", "NW2", "RW2", "+ "}, // 白棋放在第二行
    {"+ ", "PW1", "PW2", "PW3", "PW4", "PW5", "PW6", "PW7", "PW8", "+ "}, // 白兵放在第一行
    {"+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ "},
    {"+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ "},
    {"+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ "},
    {"+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ "},
    {"+ ", "PB1", "PB2", "PB3", "PB4", "PB5", "PB6", "PB7", "PB8", "+ "}, // 黑兵放在第七行
    {"+ ", "RB1", "NB1", "BB1", "QB1", "KB2", "BB2", "NB2", "RB2", "+ "}, // 黑棋放在第八行
    {"+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ ", "+ "}};

// 直接定义棋盘位置上的棋子
// String id_b[10][10] = {
//        {" ", " ",  " ",  " ",  " ",  " ",  " ",  " ",  " ",  " "},
//        {" ", "RB", "NB", "BB", "QB", "KB", "BB", "NB", "RB", " "},  // 黑棋放在第八行
//        {" ", "PB", "PB", "PB", "PB", "PB", "PB", "PB", "PB", " "},  // 黑兵放在第七行
//        {" ", " ",  " ",  " ",  " ",  " ",  " ",  " ",  " ",  " "},
//        {" ", " ",  " ",  " ",  " ",  " ",  " ",  " ",  " ",  " "},
//        {" ", " ",  " ",  " ",  " ",  " ",  " ",  " ",  " ",  " "},
//        {" ", " ",  " ",  " ",  " ",  " ",  " ",  " ",  " ",  " "},
//        {" ", "PW", "PW", "PW", "PW", "PW", "PW", "PW", "PW", " "},  // 白兵放在第一行
//        {" ", "RW", "NW", "BW", "KW", "QW", "BW", "NW", "RW", " "},  // 白棋放在第二行
//        {" ", " ",  " ",  " ",  " ",  " ",  " ",  " ",  " ",  " "}
//};
// 重置棋盘函数
void resetBoard()
{
    // 直接更新全局 id_w 数组
    id_w[0][0] = "+ ";
    id_w[0][1] = "+ ";
    id_w[0][2] = "+ ";
    id_w[0][3] = "+ ";
    id_w[0][4] = "+ ";
    id_w[0][5] = "+ ";
    id_w[0][6] = "+ ";
    id_w[0][7] = "+ ";
    id_w[0][8] = "+ ";
    id_w[0][9] = "+ ";
    id_w[1][0] = "+ ";
    id_w[1][1] = "RW1";
    id_w[1][2] = "NW1";
    id_w[1][3] = "BW1";
    id_w[1][4] = "QW1";
    id_w[1][5] = "KW2";
    id_w[1][6] = "BW2";
    id_w[1][7] = "NW2";
    id_w[1][8] = "RW2";
    id_w[1][9] = "+ ";
    id_w[2][0] = "+ ";
    id_w[2][1] = "PW1";
    id_w[2][2] = "PW2";
    id_w[2][3] = "PW3";
    id_w[2][4] = "PW4";
    id_w[2][5] = "PW5";
    id_w[2][6] = "PW6";
    id_w[2][7] = "PW7";
    id_w[2][8] = "PW8";
    id_w[2][9] = "+ ";
    id_w[3][0] = "+ ";
    id_w[3][1] = "+ ";
    id_w[3][2] = "+ ";
    id_w[3][3] = "+ ";
    id_w[3][4] = "+ ";
    id_w[3][5] = "+ ";
    id_w[3][6] = "+ ";
    id_w[3][7] = "+ ";
    id_w[3][8] = "+ ";
    id_w[3][9] = "+ ";
    id_w[4][0] = "+ ";
    id_w[4][1] = "+ ";
    id_w[4][2] = "+ ";
    id_w[4][3] = "+ ";
    id_w[4][4] = "+ ";
    id_w[4][5] = "+ ";
    id_w[4][6] = "+ ";
    id_w[4][7] = "+ ";
    id_w[4][8] = "+ ";
    id_w[4][9] = "+ ";
    id_w[5][0] = "+ ";
    id_w[5][1] = "+ ";
    id_w[5][2] = "+ ";
    id_w[5][3] = "+ ";
    id_w[5][4] = "+ ";
    id_w[5][5] = "+ ";
    id_w[5][6] = "+ ";
    id_w[5][7] = "+ ";
    id_w[5][8] = "+ ";
    id_w[5][9] = "+ ";
    id_w[6][0] = "+ ";
    id_w[6][1] = "+ ";
    id_w[6][2] = "+ ";
    id_w[6][3] = "+ ";
    id_w[6][4] = "+ ";
    id_w[6][5] = "+ ";
    id_w[6][6] = "+ ";
    id_w[6][7] = "+ ";
    id_w[6][8] = "+ ";
    id_w[6][9] = "+ ";
    id_w[7][0] = "+ ";
    id_w[7][1] = "PB1";
    id_w[7][2] = "PB2";
    id_w[7][3] = "PB3";
    id_w[7][4] = "PB4";
    id_w[7][5] = "PB5";
    id_w[7][6] = "PB6";
    id_w[7][7] = "PB7";
    id_w[7][8] = "PB8";
    id_w[7][9] = "+ ";
    id_w[8][0] = "+ ";
    id_w[8][1] = "RB1";
    id_w[8][2] = "NB1";
    id_w[8][3] = "BB1";
    id_w[8][4] = "QB1";
    id_w[8][5] = "KB2";
    id_w[8][6] = "BB2";
    id_w[8][7] = "NB2";
    id_w[8][8] = "RB2";
    id_w[8][9] = "+ ";
    id_w[9][0] = "+ ";
    id_w[9][1] = "+ ";
    id_w[9][2] = "+ ";
    id_w[9][3] = "+ ";
    id_w[9][4] = "+ ";
    id_w[9][5] = "+ ";
    id_w[9][6] = "+ ";
    id_w[9][7] = "+ ";
    id_w[9][8] = "+ ";
    id_w[9][9] = "+ ";
}

void print2DArray_string(String arr[][10], int rows, int cols)
{
    Serial.println("棋子id状态"); // 换行
    Serial.println();             // 换行
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            Serial.print(arr[i][j]);
            Serial.print("  "); // 用制表符分隔元素
        }
        Serial.println(); // 换行
    }
}

void print2DArray_char(char arr[][10], int rows, int cols)
{
    Serial.println("原始棋盘（供路径规划用）"); // 换行
    Serial.println();                           // 换行
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            Serial.print(arr[i][j]);
            Serial.print(" "); // 用制表符分隔元素
        }
        Serial.println(); // 换行
    }
}

/**
 * @brief 将1D数组转换为2D数组
 * @param arr1D 输入的1D数组
 * @param arr2D 输出的2D数组
 * @param rows 行数
 * @param cols 列数
 */
void convert1DTo2D(char arr1D[], char arr2D[][10], int rows, int cols)
{
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            arr2D[i][j] = arr1D[i * cols + j]; // 通过公式将1D数组的元素放入2D数组中
        }
    }
}

/**
 * @brief 旋转二维数组90度
 * @param input 输入的2D数组
 * @param output 旋转后的2D数组
 */
void rotate90Degrees(char input[10][10], char output[10][10])
{
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            output[j][9 - i] = input[i][j]; // 通过对称交换元素来实现旋转
        }
    }
}

/**
 * @brief 水平翻转二维数组
 * @param input 输入的2D数组
 * @param output 翻转后的2D数组
 */
void flipHorizontally(char input[10][10], char output[10][10])
{
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 5; j++)
        { // 只需要翻转前5列，后5列会自动翻转
            // 交换左右两侧的元素
            char temp = input[i][j];
            output[i][j] = input[i][9 - j];
            output[i][9 - j] = temp;
        }
    }
}

/**
 * @brief 复制二维数组
 * @param input 输入的2D数组
 * @param output 复制后的2D数组
 */
void copyArray(char input[10][10], char output[10][10])
{
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            output[i][j] = input[i][j]; // 逐个元素复制
        }
    }
}

/**
 * @brief 查找给定网格坐标的函数，返回行列坐标
 * @param pos 网格坐标
 * @return GridPosition 包含行列坐标的结构体
 */
GridPosition getGridCoordinates(const String &pos)
{
    GridPosition result = {-1, -1}; // 默认值表示未找到

    // 遍历整个网格，查找对应位置
    for (int row = 0; row < 10; ++row)
    {
        for (int col = 0; col < 10; ++col)
        {
            if (grid[row][col] == pos)
            { // 如果匹配则返回坐标
                result.row = row * 2;
                result.col = col * 2;
                return result;
            }
        }
    }

    return result; // 如果没有找到对应的名字，返回 (-1, -1)
}

/**
 * @brief 删除棋子
 * @param position 棋子位置
 */
void deletePiece(String position)
{
    int row, col;
    bool found = false;

    // 查找对应位置的索引
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            if (grid[i][j] == position)
            {
                row = i;
                col = j;
                found = true;
                break;
            }
        }
        if (found)
            break;
    }

    if (found)
    {
        // 删除棋子
        id_board = id_w[row][col];
        id_w[row][col] = "+ ";
        if (print_key)
        {
            Serial.print(id_w[row][col]);
            Serial.print("已删除棋子在: ");
            Serial.println(position);
        }
    }
    else
    {
        if (print_key)
        {
            Serial.println("无效的坐标，请重新输入。");
        }
    }
}

/**
 * @brief 返回棋子
 * @param position 棋子位置
 * @return String 棋子ID
 */
String returnPiece(String position)
{
    int row, col;
    bool found = false;

    // 查找对应位置的索引
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            if (grid[i][j] == position)
            {
                row = i;
                col = j;
                found = true;
                break;
            }
        }
        if (found)
            break;
    }

    if (found)
    {
        // 返回
        return id_w[row][col];
    }
    else
    {
        if (print_key)
        {
            Serial.println("无效的坐标，请重新输入。");
        }
    }
}

/**
 * @brief 添加棋子
 * @param position 棋子位置
 * @param piece 棋子ID
 */
void addPiece(String position, String piece)
{
    int row, col;
    bool found = false;

    // 查找对应位置的索引
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            if (grid[i][j] == position)
            {
                row = i;
                col = j;
                found = true;
                break;
            }
        }
        if (found)
            break;
    }

    if (found)
    {
        id_w[row][col] = piece;
        if (print_key)
        {
            Serial.print(id_w[row][col]);
            Serial.print("已添加棋子在: ");
            Serial.println(position);
        }
    }
    else
    {
        if (print_key)
        {
            Serial.println("无效的坐标，请重新输入。");
        }
    }
}

/**
 * @brief 检查棋子是否到达指定位置
 * @param position 棋子位置
 * @return bool 如果棋子到达指定位置返回true，否则返回false
 */
bool checkIfMovedToPosition(String position)
{
    // 获取对应位置的行列索引
    int row, col;
    bool found = false;

    // 查找输入位置的行列索引
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            if (grid[i][j] == position)
            {
                row = i;
                col = j;
                if (print_key)
                {
                    Serial.printf("棋子所在棋格坐标：%d,%d", i, j);
                }

                found = true;
                break;
            }
        }
        if (found)
            break;
    }

    if (found)
    {
        if (finalArr[row][col] == 'w')
        {
            if (print_key)
            {
                Serial.print("棋子已到达 ");
                Serial.println(position);
            }

            id_w[row][col] = id_board;

            return true; // 棋子已到达指定位置并且位置上有 'w'，返回 true
        }
        else
        {
            if (print_key)
            {
                Serial.print("棋子未到达 ");
                Serial.println(position);
            }
            return false; // 棋子未到达指定位置或位置上不是 'w'，返回 false
        }
    }
    else
    {
        if (print_key)
        {
            Serial.println("无效的坐标，请重新输入。");
        }
        return false; // 输入的坐标无效，返回 false
    }
}

/**
 * @brief 检查指定坐标位置是否有棋子，并返回一个数组，第一个元素是棋子的ID，第二个元素是坐标字符串
 * @param row 行号
 * @param col 列号
 * @return String* 包含棋子ID和坐标的数组
 */
String *checkIfPieceAtPosition(int row, int col)
{
    // 返回一个临时的 String 数组
    static String result[2]; // 使用 static 确保返回数组不会在函数返回后被销毁

    // 检查坐标是否有效
    if (row < 0 || row >= 10 || col < 0 || col >= 10)
    {
        if (print_key)
        {
            Serial.println("无效的坐标，请重新输入。");
        }
        result[0] = ""; // 无效坐标时，返回空字符串
        result[1] = "";
        return result; // 返回数组
    }

    // 检查该位置是否有棋子
    if (id_w[row][col] != "+ ")
    { // 检查位置是否有棋子（假设空白是 ' '，'+' 为特殊标记）
        if (print_key)
        {
            Serial.print("位置 ");
            Serial.print(row);
            Serial.print(",");
            Serial.print(col);
            Serial.print(" 上有棋子，ID: ");
            Serial.println(id_w[row][col]);
        }
        // 返回棋子的 ID 和坐标
        result[0] = id_w[row][col];                   // 存储棋子 ID
        result[1] = String(row) + ", " + String(col); // 存储坐标
    }
    else
    {
        if (print_key)
        {
            Serial.print("位置 ");
            Serial.print(row);
            Serial.print(",");
            Serial.print(col);
            Serial.println(" 上没有棋子");
        }
        result[0] = ""; // 无效坐标时，返回空字符串
        result[1] = "";
    }

    return result; // 返回结果数组
}

GridPosition checkEmpty_b_p()
{
    GridPosition result = {-1, -1}; // 默认值表示未找到
    // 遍历列 0 到列 8
    for (int col = 1; col <= 8; col++)
    {
        // 检查当前列的位置是否为空
        if (id_w[0][col] == "+ ")
        {
            result.row = 0; // 行固定为 0，因为我们只检查第 0 行
            result.col = col * 2;
            return result;
        }
    }
    return result; // 如果没有找到空位置，返回 (-1, -1)
}

GridPosition checkEmpty_w_p()
{
    GridPosition result = {-1, -1}; // 默认值表示未找到
    // 遍历列 0 到列 8
    for (int col = 1; col <= 8; col++)
    {
        // 检查当前列的位置是否为空
        if (id_w[9][col] == "+ ")
        {
            result.row = 9 * 2; // 行固定为 0，因为我们只检查第 0 行
            result.col = col * 2;
            return result;
        }
    }
    return result; // 如果没有找到空位置，返回 (-1, -1)
}

/**
 * @brief 检查黑方第0列是否有空位
 * @return GridPosition 包含行列坐标的结构体
 */
GridPosition checkEmpty_b_0()
{
    GridPosition result = {-1, -1}; // 默认值表示未找到

    // 检查列 0 和列 9
    for (int row = 4; row >= 1; row--)
    {
        // 检查第 0 列
        if (id_w[row][0] == "+ ")
        {
            result.row = row * 2; // 行固定为 0，根据需要调整
            result.col = 0;
            return result;
        }
    }
    return result; // 如果没有找到空位置，返回 (-1, -1)
}

/**
 * @brief 检查黑方第9列是否有空位
 * @return GridPosition 包含行列坐标的结构体
 */
GridPosition checkEmpty_b_9()
{
    GridPosition result = {-1, -1}; // 默认值表示未找到

    // 检查列 0 和列 9
    for (int row = 4; row >= 1; row--)
    {
        // 检查第 9 列
        if (id_w[row][9] == "+ ")
        {
            result.row = row * 2; // 行固定为 0，根据需要调整
            result.col = 9 * 2;
            return result;
        }
    }
    return result; // 如果没有找到空位置，返回 (-1, -1)
}

/**
 * @brief 检查白方第0列是否有空位
 * @return GridPosition 包含行列坐标的结构体
 */
GridPosition checkEmpty_w_0()
{
    GridPosition result = {-1, -1}; // 默认值表示未找到

    // 检查列 0 和列 9
    for (int row = 5; row <= 9; row++)
    {
        // 检查第 0 列
        if (id_w[row][0] == "+ ")
        {
            result.row = row * 2; // 行固定为 0，根据需要调整
            result.col = 0;
            return result;
        }
    }
    return result; // 如果没有找到空位置，返回 (-1, -1)
}

/**
 * @brief 检查白方第9列是否有空位
 * @return GridPosition 包含行列坐标的结构体
 */
GridPosition checkEmpty_w_9()
{
    GridPosition result = {-1, -1}; // 默认值表示未找到
    // 检查列 0 和列 9
    for (int row = 5; row <= 9; row++)
    {
        // 检查第 9 列
        if (id_w[row][9] == "+ ")
        {
            result.row = row * 2; // 行固定为 0，根据需要调整
            result.col = 9 * 2;
            return result;
        }
    }
    return result; // 如果没有找到空位置，返回 (-1, -1)
}

/**
 * @brief 检查棋子丢失情况
 * @return String 丢失的棋子信息
 */
String verifyPieceStatus()
{
    String result = ""; // 用来累积返回的结果

    for (int p = 0; p < 12; p++)
    {
        String pieceName = pieces[p]; // 获取当前棋子的名称

        // 遍历棋盘，查找棋子
        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 10; j++)
            {
                if (id_w[i][j] == pieceName)
                { // 找到指定棋子
                    if (finalArr[i][j] != 'w')
                    { // 如果该位置没有棋子
                        result += id_w[i][j];
                        result += ",Piece lost at:";
                        result += grid[i][j];
                        result += "\n";
                    }
                }
            }
        }
    }
    return result; // 返回丢失的棋子信息
}

/**
 * @brief 转换棋盘
 */
void transformBoard()
{
    ////转换棋盘
    // 调用函数将1D字符数组转换为2D字符数组
    convert1DTo2D(newBoard, arr2D, 10, 10);
    // 旋转90度
    rotate90Degrees(arr2D, rotatedArr);
    // 水平翻转
    flipHorizontally(rotatedArr, finalArr);
}

/**
 * @brief 绘制等边三角形
 * @param start_x 起点X坐标（左下角）
 * @param start_y 起点Y坐标
 * @param side_length 边长（单位：mm）
 */
void drawTriangle(float start_x, float start_y, float side_length)
{
    //    controlElectromagnet(true);
    float height = side_length * sqrt(3) / 2; // 等边三角形高度

    // 移动到起点
    magnet_move(start_x, start_y, 1);

    // 绘制三条边
    magnet_move(start_x + side_length, start_y, 1);              // 右移底边
    magnet_move(start_x + side_length / 2, start_y + height, 1); // 上移顶点
    magnet_move(start_x, start_y, 1);                            // 返回起点（闭合）
    controlElectromagnet(false);
}

/**
 * @brief 绘制正方形
 * @param start_x 起点X坐标（左下角）
 * @param start_y 起点Y坐标
 * @param side_length 边长（单位：mm）
 */
void drawSquare(float start_x, float start_y, float side_length)
{
    //    controlElectromagnet(true);
    // 移动到起点
    magnet_move(start_x, start_y, 3);

    // 绘制四条边
    magnet_move(start_x + side_length, start_y, 3);               // 右移
    magnet_move(start_x + side_length, start_y + side_length, 3); // 上移
    magnet_move(start_x, start_y + side_length, 3);               // 左移
    magnet_move(start_x, start_y, 3);                             // 下移（闭合）
                                                                  //    controlElectromagnet(false);
    controlElectromagnet(false);
    // Serial.println("Movement completed.");
}

/**
 * @brief 绘制圆形
 * @param center_x 圆心X坐标（单位：mm）
 * @param center_y 圆心Y坐标（单位：mm）
 * @param radius 半径（单位：mm）
 * @param segments 分段数（越高越圆滑，建议 ≥60）
 */
void drawCircle(float center_x, float center_y, float radius, int segments)
{
    //    controlElectromagnet(true);  // 启动电磁铁
    float angle_increment = 2 * M_PI / segments;

    for (int i = 0; i <= segments; i++)
    {
        float angle = i * angle_increment;
        float x = center_x + radius * cos(angle);
        float y = center_y + radius * sin(angle);

        // 移动电磁铁到当前点
        magnet_move(x, y, 1); // magnet_num根据实际情况调整
    }
    controlElectromagnet(false); // 关闭电磁铁
    if (print_key)
    {
        Serial.println("Movement completed.");
    }
}

/**
 * @brief 往返运动并计算平均线速度
 * @param start_x 起点X坐标（单位：mm）
 * @param start_y 起点Y坐标
 * @param end_x 终点X坐标
 * @param end_y 终点Y坐标
 * @param cycles 往返次数（1次往返 = 去 + 回）
 * @param magnet_num 电磁铁编号
 * @return float 平均线速度（单位：mm/s）
 */
float runRoundTripWithSpeed(float start_x, float start_y, float end_x, float end_y, int cycles, int magnet_num)
{
    //    controlElectromagnet(true);

    // 记录开始时间（毫秒）
    unsigned long start_time = millis();

    for (int i = 0; i < cycles; i++)
    {
        magnet_move(end_x, end_y, magnet_num);     // 去程
        magnet_move(start_x, start_y, magnet_num); // 返程
    }

    // 记录结束时间（毫秒）
    unsigned long end_time = millis();
    controlElectromagnet(false);

    // 计算总距离（单位：mm）
    float dx = end_x - start_x;
    float dy = end_y - start_y;
    float single_trip_distance = sqrt(dx * dx + dy * dy);     // 单程距离
    float total_distance = 2 * single_trip_distance * cycles; // 往返总距离

    // 计算总时间（单位：秒）
    float total_time_sec = (end_time - start_time) / 1000.0;

    // 计算平均线速度（mm/s）
    float linear_speed = total_distance / total_time_sec;

    // 通过串口输出结果
    if (print_key)
    {
        Serial.print("总距离: ");
        Serial.print(total_distance);
        Serial.print(" mm, 总时间: ");
        Serial.print(total_time_sec);
        Serial.print(" s, 平均速度: ");
        Serial.print(linear_speed);
        Serial.println(" mm/s");
    }

    return linear_speed;
}

// 队列配置
const int QUEUE_SIZE = 200; // 根据需求调整队列容量
ChessMove moveQueue[QUEUE_SIZE];
int queueHead = 0;
int queueTail = 0;
int moveCount = 0;

/**
 * @brief 记录棋步
 * @param piece 棋子ID
 * @param start 起始位置
 * @param end 结束位置
 * @param magnet 电磁铁编号
 */
void logMove(String piece, String start, String end, int magnet)
{
    moveQueue[queueTail] = {piece, start, end, magnet};
    queueTail = (queueTail + 1) % QUEUE_SIZE;

    if (moveCount < QUEUE_SIZE)
    {
        moveCount++;
    }
    else
    {
        queueHead = (queueHead + 1) % QUEUE_SIZE; // 覆盖最旧数据
    }

    // 更新棋子记录
    if (pieceRecords.find(piece) == pieceRecords.end())
    {
        // 新棋子：记录起点和终点
        pieceRecords[piece] = {start, end, magnet};
    }
    else
    {
        // 已有棋子：仅更新终点
        pieceRecords[piece].end = end;
        pieceRecords[piece].magnet = magnet;
    }

    // 打印当前队列状态
    if (print_key)
    {
        Serial.println("\n=== 最新棋步记录 ===");
        Serial.print("当前存储: ");
        Serial.print(moveCount);
        Serial.print("/");
        Serial.println(QUEUE_SIZE);
    }

    // 遍历有效记录
    for (int i = 0; i < moveCount; i++)
    {
        int index = (queueHead + i) % QUEUE_SIZE;
        if (print_key)
        {
            Serial.print(i + 1);
            Serial.print(". ");
            Serial.print(moveQueue[index].piece);
            Serial.print("→");
            Serial.print(moveQueue[index].startPos);
            Serial.print("→");
            Serial.print(moveQueue[index].endPos);
            Serial.print(" (电磁铁#");
            Serial.print(moveQueue[index].magnetNum);
            Serial.println(")");
        }
    }
    if (print_key)
    {
        Serial.println("====================");
    }
}

/**
 * @brief 获取指定步数历史
 * @param stepsBack 步数（0=最新，1=上一步...）
 * @return ChessMove 包含棋子ID、起始位置、结束位置和电磁铁编号的结构体
 */
ChessMove getMoveHistory(int stepsBack)
{
    if (stepsBack >= moveCount)
        return {"", "", "", -1};

    int index = (queueTail - 1 - stepsBack + QUEUE_SIZE) % QUEUE_SIZE;
    return moveQueue[index];
}

// ================= 结果输出 =================
// 修改打印函数
// 打印所有出现过的棋子轨迹
void printPieceJourneys()
{
    if (print_key)
    {
        Serial.println("\n=== 所有棋子轨迹 ===");
        Serial.println("棋子   起点 → 终点    最后磁铁");
        Serial.println("------------------------------");
    }

    for (const auto &[piece, record] : pieceRecords)
    {
        // 使用统一格式化输出
        if (print_key)
        {
            Serial.printf("%-6s %3s → %-3s   #%-2d\n",
                          piece.c_str(),
                          record.start.c_str(),
                          record.end.c_str(),
                          record.magnet);
        }
    }
    if (print_key)
    {
        Serial.println("======================");
    }
}

// 删除最后number条棋步记录
void clearMoveHistory(int number)
{
    number = min(number, moveCount); // 不能超过当前存储量
    if (number <= 0)
        return;

    // 调整队列指针和计数
    moveCount -= number;
    queueTail = (queueTail - number + QUEUE_SIZE) % QUEUE_SIZE;

    // 清空棋子记录并重新构建
    pieceRecords.clear();
    for (int i = 0; i < moveCount; i++)
    {
        int index = (queueHead + i) % QUEUE_SIZE; // 从队列头部开始遍历
        ChessMove move = moveQueue[index];
        if (pieceRecords.find(move.piece) == pieceRecords.end())
        {
            // 新棋子：记录起点和终点
            pieceRecords[move.piece] = {move.startPos, move.endPos, move.magnetNum};
        }
        else
        {
            // 已有棋子：更新终点信息
            pieceRecords[move.piece].end = move.endPos;
            pieceRecords[move.piece].magnet = move.magnetNum;
        }
    }

    // 打印删除后状态
    if (print_key)
    {
        Serial.println("\n=== 删除后棋步记录 ===");
        Serial.print("剩余存储: ");
        Serial.print(moveCount);
        Serial.print("/");
        Serial.println(QUEUE_SIZE);
    }
    for (int i = 0; i < moveCount; i++)
    {
        int index = (queueHead + i) % QUEUE_SIZE;
        if (print_key)
        {
            Serial.print(i + 1);
            Serial.print(". ");
            Serial.print(moveQueue[index].piece);
            Serial.print("→");
            Serial.print(moveQueue[index].startPos);
            Serial.print("→");
            Serial.print(moveQueue[index].endPos);
            Serial.print(" (电磁铁#");
            Serial.print(moveQueue[index].magnetNum);
            Serial.println(")");
        }
    }
    if (print_key)
    {
        Serial.println("======================");
    }
}

/**
 * @brief 检查指定位置是否为空
 * @param position 位置坐标
 * @return bool 如果为空返回true，否则返回false
 */
bool checkIfEmpty(String position)
{

    // 获取对应位置的行列索引
    int row, col;
    bool found = false;

    // 查找输入位置的行列索引
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            if (grid[i][j] == position)
            {
                row = i;
                col = j;
                if (print_key)
                {
                    Serial.printf("棋子所在棋格坐标：%d,%d", i, j);
                }

                found = true;
                break;
            }
        }
        if (found)
            break;
    }

    if (found)
    {
        if (finalArr[row][col] == '+')
        {
            return true; // 棋子已到达指定位置并且位置上有 'w'，返回 true
        }
        else
        {
            return false; // 棋子未到达指定位置或位置上不是 'w'，返回 false
        }
    }
    else
    {
        if (print_key)
        {
            Serial.println("无效的坐标，请重新输入。");
        }
        return false; // 输入的坐标无效，返回 false
    }
}

String lookupIdInGridRange() // 待优化
{
    int row, col;
    bool found = false;

    // 查找对应位置的索引
    for (int i = 3; i < 6; i++)
    {
        for (int j = 3; j < 7; j++)
        {
            if (print_key)
            {
                Serial.printf("finalArr %c ", finalArr[i][j]);
            }
            if (finalArr[i][j] == '+')
            {
                row = i;
                col = j;
                found = true;
                break;
            }
        }
        if (found)
            break;
    }

    if (found)
    {
        // 返回
        return grid[row][col];
    }
    else
    {
        if (print_key)
        {
            Serial.println("没找到任何空位");
        }
    }
}

/**
 * @brief 校验一次移动是否已经在ID板状态中生效
 * @param before 移动前的 10x10 棋盘状态（'w' 表示有棋子，'+' 表示无）
 * @param after  移动后的 10x10 棋盘状态
 * @param startPosAlt 起点的两位索引（00-99）
 * @param endPosAlt   终点的两位索引（00-99）
 * @return true 当且仅当 起点从 'w' 变成 '+' 且 终点从 '+' 变成 'w'
 */
bool verifyMoveApplied(const char before[10][10], const char after[10][10], int startPosAlt, int endPosAlt)
{
    int startRow = startPosAlt / 10;
    int startCol = startPosAlt % 10;
    int endRow = endPosAlt / 10;
    int endCol = endPosAlt % 10;

    // 边界检查
    if (startRow < 0 || startRow > 9 || startCol < 0 || startCol > 9 ||
        endRow < 0 || endRow > 9 || endCol < 0 || endCol > 9)
    {
        return false;
    }

    bool startChanged = (before[startRow][startCol] == 'w') && (after[startRow][startCol] == '+');
    bool endChanged = (before[endRow][endCol] == '+') && (after[endRow][endCol] == 'w');
    return startChanged && endChanged;
}
int processString_alt(String str)
{
    // 1. 交换首位与次位字符（如果字符串长度至少为2）
    if (str.length() >= 2)
    {
        char first = str.charAt(0);
        char second = str.charAt(1);
        str.setCharAt(0, second);
        str.setCharAt(1, first);
    }

    // 2. 将 a-h/A-H 转换为对应的 1-8
    for (unsigned int i = 0; i < str.length(); ++i)
    {
        char c = str.charAt(i);
        if (c >= 'a' && c <= 'h')
        {
            str.setCharAt(i, static_cast<char>('1' + (c - 'a')));
        }
        else if (c >= 'A' && c <= 'H')
        {
            str.setCharAt(i, static_cast<char>('1' + (c - 'A')));
        }
    }
    // 3. 将字符转成数字
    int value = 0;
    int count = 0;
    for (unsigned int i = 0; i < str.length() && count < 2; ++i)
    {
        char c = str.charAt(i);
        if (c >= '0' && c <= '9')
        {
            value = value * 10 + (c - '0');
            count++;
        }
    }
    return value;
}
